package cn.turboinfo.dongying.api.provider.admin.impl.menu;

import cn.turboinfo.dongying.api.domain.admin.service.menu.MenuService;
import cn.turboinfo.dongying.api.domain.admin.service.permission.PermissionService;
import cn.turboinfo.dongying.api.domain.common.service.role.RolePermissionService;
import cn.turboinfo.dongying.api.domain.common.service.user.SysUserRoleService;
import cn.turboinfo.dongying.api.entity.admin.pojo.menu.Menu;
import cn.turboinfo.dongying.api.entity.admin.pojo.permission.Permission;
import cn.turboinfo.dongying.api.entity.admin.pojo.role.RolePermission;
import cn.turboinfo.dongying.api.entity.admin.pojo.user.SysUserRole;
import cn.turboinfo.dongying.api.provider.admin.repository.database.permission.PermissionDAO;
import net.sunshow.toolkit.core.base.enums.YesNoStatus;
import net.sunshow.toolkit.core.qbean.helper.component.mapper.BeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

@Service
public class MenuServiceImpl implements MenuService {

    private SysUserRoleService sysUserRoleService;

    private RolePermissionService rolePermissionService;

    private PermissionService permissionService;

    private PermissionDAO permissionDAO;

    private Stream<Permission> findPermissionStreamBySysUserId(Long sysUserId) {
        List<SysUserRole> sysUserRoleList = sysUserRoleService.findBySysUserId(sysUserId);

        // 所有角色的权限列表
        List<RolePermission> rolePermissionList = rolePermissionService.findByRoleIdCollection(sysUserRoleList.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet()));

        // 仅处理可见的 并进行排序
        List<Permission> permissionList = permissionService.findByIdCollection(rolePermissionList.stream().map(RolePermission::getPermissionId).collect(Collectors.toSet()));

        return permissionList.stream();
    }

    @Override
    public List<Menu> findBySysUserIdAll(Long sysUserId) {
        return permissionStreamToMenuList(findPermissionStreamBySysUserId(sysUserId));
    }

    @Override
    public List<Menu> findBySysUserId(Long sysUserId) {
        return permissionStreamToMenuList(findPermissionStreamBySysUserId(sysUserId)
                .filter(p -> p.getVisibleStatus() == YesNoStatus.YES));
    }

    @Override
    public List<Menu> findAllWithHierarchy() {
        return permissionStreamToMenuList(StreamSupport.stream(permissionDAO.findAll().spliterator(), false).map(permissionPO -> BeanMapper.map(permissionPO, Permission.class)));
    }

    @Override
    public List<Menu> findRoleAccessibleWithHierarchy(Long roleId) {
        return permissionStreamToMenuList(
                StreamSupport.stream(permissionDAO.findAll().spliterator(), false)
                        .filter(permissionPO -> Objects.equals(permissionPO.getRoleId(), 0L) || Objects.equals(permissionPO.getRoleId(), roleId))
                        .map(permissionPO -> BeanMapper.map(permissionPO, Permission.class))
        );
    }

    private List<Menu> permissionStreamToMenuList(Stream<Permission> permissionStream) {
        List<Menu> menuList = new ArrayList<>();

        // 先遍历转换
        Map<Long, Menu> menuMap = new LinkedHashMap<>();
        permissionStream
                // .filter(p -> p.getVisibleStatus() == YesNoStatus.YES)
                // 不显示菜单但存在页面组件的也需要返回给前端渲染路由表
                // 非页面组件的权限也要返回给前端做接口权限资源分配
                // .filter(p -> !p.getComponent().isEmpty())
                .sorted((p1, p2) -> {
                    if (p1.getParentId().equals(p2.getParentId())) {
                        if (p1.getSortValue().equals(p2.getSortValue())) {
                            return p1.getId().compareTo(p2.getId());
                        }
                        return p1.getSortValue().compareTo(p2.getSortValue());
                    }
                    return p1.getParentId().compareTo(p2.getParentId());
                })
                .forEach(permission -> {
                    if (menuMap.containsKey(permission.getId())) {
                        return;
                    }
                    // 构建当前项 Menu
                    Menu menu = new Menu();
                    menu.setId(permission.getId());
                    menu.setName(permission.getName());
                    menu.setDescription(permission.getDescription());
                    menu.setResource(permission.getResource());
                    menu.setUrl(permission.getUrl());
                    menu.setComponent(permission.getComponent());
                    menu.setVisibleStatus(permission.getVisibleStatus());
                    menu.setParentId(permission.getParentId());
                    menu.setSubList(new ArrayList<>());
                    menu.setIcon(permission.getIcon());

                    menuMap.put(permission.getId(), menu);
                });

        // 构建层级
        menuMap.values().forEach(menu -> {
            if (menu.getParentId() == 0) {
                menuList.add(menu);
            } else {
                if (menuMap.containsKey(menu.getParentId())) {
                    menuMap.get(menu.getParentId()).getSubList().add(menu);
                }
            }
        });

        return menuList;
    }

    @Autowired
    public void setSysUserRoleService(SysUserRoleService sysUserRoleService) {
        this.sysUserRoleService = sysUserRoleService;
    }

    @Autowired
    public void setRolePermissionService(RolePermissionService rolePermissionService) {
        this.rolePermissionService = rolePermissionService;
    }

    @Autowired
    public void setPermissionService(PermissionService permissionService) {
        this.permissionService = permissionService;
    }

    @Autowired
    public void setPermissionDAO(PermissionDAO permissionDAO) {
        this.permissionDAO = permissionDAO;
    }
}
